import Field from '@/YmForm/Field';
import {
  Checkbox,
  DatePicker,
  Input,
  InputNumber,
  Popover,
  Radio,
  Select,
} from 'antd';
import React, { useCallback, useState } from 'react';
import type { FormItemProps, InputRangeProps } from './interface';
// import { FormItemInputContext } from '@/YmForm/context'
import { FormItemInputContext } from 'antd/es/form/context'; //使得 antd-Input能使用该Context

const { RangePicker } = DatePicker;

const InputRange = (props: InputRangeProps) => {
  const { value = [undefined, undefined], onChange, ...restProps } = props;
  // 输入值改变
  const handleInput = (
    e: React.ChangeEvent<HTMLInputElement>,
    type: 'prev' | 'next',
  ) => {
    const v = e.target?.value;
    const nValue = [...value];
    if (type === 'prev') {
      nValue[0] = v;
    }
    if (type === 'next') {
      nValue[1] = v;
    }
    onChange?.(nValue);
  };

  return (
    <div
      className="inputRange"
      style={{ display: 'inline-flex', alignItems: 'center' }}
    >
      <Input
        value={value?.[0]}
        placeholder="请输入"
        onChange={(e) => handleInput(e, 'prev')}
        {...restProps}
      />
      ~
      <Input
        value={value?.[1]}
        placeholder="请输入"
        onChange={(e) => handleInput(e, 'next')}
        {...restProps}
      />
    </div>
  );
};

function ErrorPopover(props: {
  errors: React.ReactNode[];
  children: React.ReactNode;
}) {
  const { errors, children } = props;
  const [visible, setVisible] = useState(false);

  return (
    <Popover
      placement="topLeft"
      trigger="hover"
      open={visible && !!errors.length}
      onOpenChange={(v) => {
        setVisible(v);
      }}
      content={
        <div className={!!errors.length ? 'ym-form-item-explain-error' : ''}>
          {errors.map((str: React.ReactNode, index: number) => {
            return (
              <div role="alert" key={index}>
                {str}
              </div>
            );
          })}
        </div>
      }
    >
      <div className="ym-input-content">
        <FormItemInputContext.Provider
          value={{ status: !!errors.length ? 'error' : '' }}
        >
          {children}
        </FormItemInputContext.Provider>
      </div>
    </Popover>
  );
}

const FormItem: React.FC<FormItemProps> = (props) => {
  const { valueType, formItemProps, record, form } = props;

  const getEditChildNode = useCallback<(control: any) => React.ReactNode>(
    (control) => {
      let tempChildNode;
      if (typeof valueType === 'function') {
        return valueType(form, record, control);
      } else if (typeof valueType === 'object' && valueType.type) {
        const { type } = valueType;
        if (type === 'input') {
          tempChildNode = <Input {...valueType.inputProps} />;
        } else if (type === 'inputRange') {
          tempChildNode = <InputRange {...valueType.inputRangeProps} />;
        } else if (type === 'inputNumber') {
          tempChildNode = <InputNumber {...valueType.inputNumberProps} />;
        } else if (type === 'date') {
          tempChildNode = <DatePicker {...valueType.datePickerProps} />;
        } else if (type === 'rangeDate') {
          tempChildNode = <RangePicker {...valueType.rangePickerProps} />;
        } else if (type === 'select') {
          tempChildNode = <Select {...valueType.selectProps} />;
        } else if (type === 'checkbox') {
          tempChildNode = <Checkbox.Group {...valueType.checkboxGroupProps} />;
        } else if (type === 'radio') {
          tempChildNode = <Radio.Group {...valueType.radioGroupProps} />;
        }
      } else {
        tempChildNode = <Input placeholder="请输入" autoComplete="off" />;
      }
      return React.cloneElement(tempChildNode as React.ReactElement, {
        ...control,
      });
    },
    [valueType, form, record],
  );

  return (
    <Field {...formItemProps}>
      {(control, { errors }) => {
        const childNode = getEditChildNode(control);
        return <ErrorPopover errors={errors}>{childNode}</ErrorPopover>;
      }}
    </Field>
  );
};

export default FormItem;
